home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / randist / shuffle.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-23  |  3.2 KB  |  125 lines

  1. /* randist/shuffle.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <config.h>
  21. #include <stdlib.h>
  22. #include <math.h>
  23. #include <gsl/gsl_rng.h>
  24. #include <gsl/gsl_randist.h>
  25.  
  26. /* Inline swap and copy functions for moving objects around */
  27.  
  28. static inline 
  29. void swap (void * base, size_t size, size_t i, size_t j)
  30. {
  31.   register char * a = size * i + (char *) base ;
  32.   register char * b = size * j + (char *) base ;
  33.   register size_t s = size ;
  34.  
  35.   if (i == j)
  36.     return ;
  37.   
  38.   do                        
  39.     {                        
  40.       char tmp = *a;                
  41.       *a++ = *b;                
  42.       *b++ = tmp;                
  43.     } 
  44.   while (--s > 0);                
  45. }
  46.  
  47. static inline void 
  48. copy (void * dest, size_t i, void * src, size_t j, size_t size)
  49. {
  50.   register char * a = size * i + (char *) dest ;
  51.   register char * b = size * j + (char *) src ;
  52.   register size_t s = size ;
  53.   
  54.   do                        
  55.     {                        
  56.       *a++ = *b++;                
  57.     } 
  58.   while (--s > 0);                
  59. }
  60.  
  61. /* Randomly permute (shuffle) N indices
  62.  
  63.    Supply an array x[N] with nmemb members, each of size size and on
  64.    return it will be shuffled into a random order.  The algorithm is
  65.    from Knuth, SemiNumerical Algorithms, v2, p139, who cites Moses and
  66.    Oakford, and Durstenfeld */
  67.  
  68. void
  69. gsl_ran_shuffle (const gsl_rng * r, void * base, size_t n, size_t size)
  70. {
  71.   size_t i ;
  72.  
  73.   for (i = n - 1; i > 0; i--)
  74.     {
  75.       size_t j = gsl_rng_uniform_int(r, i+1); /* originally (i + 1) * gsl_rng_uniform (r) */
  76.  
  77.       swap (base, size, i, j) ;
  78.     }
  79. }
  80.  
  81. int
  82. gsl_ran_choose (const gsl_rng * r, void * dest, size_t k, void * src, 
  83.          size_t n, size_t size)
  84. {
  85.   size_t i, j = 0;
  86.  
  87.   /* Choose k out of n items, return an array x[] of the k items.
  88.      These items will prevserve the relative order of the original
  89.      input -- you can use shuffle() to randomize the output if you
  90.      wish */
  91.  
  92.   if (k > n)
  93.     {
  94.       GSL_ERROR ("k is greater than n, cannot sample more than n items",
  95.                  GSL_EINVAL) ;
  96.     }
  97.  
  98.   for (i = 0; i < n && j < k; i++)
  99.     {
  100.       if ((n - i) * gsl_rng_uniform (r) < k - j)
  101.     {
  102.       copy (dest, j, src, i, size) ;
  103.       j++ ;
  104.     }
  105.     }
  106.  
  107.   return GSL_SUCCESS;
  108. }
  109.  
  110. void
  111. gsl_ran_sample (const gsl_rng * r, void * dest, size_t k, void * src, 
  112.         size_t n, size_t size)
  113. {
  114.   size_t i, j = 0;
  115.  
  116.   /* Choose k out of n items, with replacement */
  117.  
  118.   for (i = 0; i < k; i++)
  119.     {
  120.       j = gsl_rng_uniform_int (r, n);  /* originally n * gsl_rng_uniform (r) */
  121.  
  122.       copy (dest, i, src, j, size) ;
  123.     }
  124. }
  125.